package com.cheer.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheer.common.Page;
import com.cheer.common.Result;
import com.cheer.controller.ValidateController;
import com.cheer.dao.LecCourseDao;
import com.cheer.dao.LecTeacherDao;
import com.cheer.dao.OaAdminDao;
import com.cheer.dao.OaLearnClassDao;
import com.cheer.dto.ImageCodeDTO;
import com.cheer.dto.LecTeacherAddDTO;
import com.cheer.dto.OaAdminAddDTO;
import com.cheer.entity.LecCourseEntity;
import com.cheer.entity.LecTeacherEntity;
import com.cheer.entity.OaAdminEntity;
import com.cheer.entity.OaLearnClassEntity;
import com.cheer.enums.AdminRoleEnum;
import com.cheer.enums.LectureTypeEnum;
import com.cheer.enums.ResourceEnum;
import com.cheer.exception.ServiceException;
import com.cheer.param.LecTeacherListParam;
import com.cheer.security.UserInfoHolder;
import com.cheer.service.*;
import com.cheer.util.ExcelsUtil;
import com.cheer.util.FileDownUtil;
import com.cheer.vo.*;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.time.temporal.TemporalAccessor;
import java.util.*;
import java.util.stream.Collectors;

@Service("lecTeacherService")
@Slf4j
public class LecTeacherServiceImpl extends ServiceImpl<LecTeacherDao, LecTeacherEntity> implements LecTeacherService {

    @Autowired
    private LecTeacherDao lecTeacherDao;

    @Autowired
    private LecCourseDao lecCourseDao;

    @Autowired
    private OaLearnClassService oaLearnClassService;

    @Autowired
    private LecCourseService lecCourseService;

    @Autowired
    private OaLearnClassDao oaLearnClassDao;

    @Autowired
    private OaAdminService oaAdminService;

    @Autowired
    private LecResourceService lecResourceService;

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private HttpServletResponse httpServletResponse;

    @Override
    public Page<LecTeacherVO> listByPage(LecTeacherListParam lecTeacherListParam) {

        String path = null;
        path = getCompletePath(path, lecTeacherListParam.getOrg());
        lecTeacherListParam.setOrgStr(path);

        IPage<LecTeacherVO> pageResult = lecTeacherDao
                .listByPage( new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(lecTeacherListParam.getPageNum()
                                , lecTeacherListParam.getPageSize()), lecTeacherListParam );

        List<LecTeacherVO> records = loadLecTeacherVOProp(pageResult.getRecords());

        return new Page<>( pageResult, records );
    }

    @Override
    public List<LecTeacherVO> list(LecTeacherListParam lecTeacherListParam) {

        return lecTeacherDao.list(lecTeacherListParam);
    }

    /**
     * 填充部门信息
     * @param records
     * @return
     */
    private List<LecTeacherVO> loadLecTeacherVOProp(List<LecTeacherVO> records) {


        List<String> paths = records.stream().map(LecTeacherVO::getPath).filter(path -> StrUtil.isNotBlank(path)).collect(Collectors.toList());
        Map<Integer, String> map = getOrgIdMapOrgName(paths);

        records.forEach( lecTeacherVO -> {
            lecTeacherVO.setOrgStr(getOrgStr(map, lecTeacherVO.getPath()));
            lecTeacherVO.setTypesStr(LectureTypeEnum.getLectureTypes(lecTeacherVO.getTypes()));
        });

        return records;
    }

    @Override
    public Map<Integer, String> getOrgIdMapOrgName(List<String> paths) {

        Map<Integer, String> map = new HashMap<>();
        if(CollectionUtil.isEmpty(paths)){
            return map;
        }
        Set<String> idSet = new HashSet<>();
        paths.forEach(path -> {
            String[] split = StringUtils.split(path, ",");
            idSet.addAll(Lists.newArrayList(split));
        });
        idSet.remove("0");

        if (CollectionUtils.isNotEmpty(idSet)) {
            oaLearnClassService.listByIds(idSet).forEach(learnClass -> map.put(learnClass.getId(), learnClass.getName()));
        }
        return map;
    }


    /**
     * 获取机构Str
     * @param map
     * @param path
     * @return
     */
    @Override
    public String getOrgStr(Map<Integer, String> map, String path) {

        String orgStr = "";
        String[] split = StringUtils.split(path, ",");
        if (ArrayUtils.isNotEmpty(split)) {
            List<String> learnClass = new ArrayList<>();
            for (String str : split) {
                if (!Objects.equals(str, "0")) {
                    if (map.get(Integer.valueOf(str)) != null) {
                        learnClass.add(map.get(Integer.valueOf(str)));
                    } else {
                        break;
                    }
                }
            }
            if (CollectionUtils.isNotEmpty(learnClass)) {
                orgStr = StringUtils.join(learnClass, "-");
            }
        }

        return orgStr;
    }

    private String getCompletePath(String path, Integer org) {

        if (org != 0) {
            OaLearnClassEntity learnClass = oaLearnClassService.getById(org);
            if (learnClass == null) {
                throw new ServiceException("单位不存在");
            }
            path = learnClass.getPath() + org + ",";
        }
        return path;
    }

    @Override
    public void download(LecTeacherListParam lecTeacherListParam) {

        Date start = new Date();
        Date date = new Date();
        String path = null;
        Integer org = lecTeacherListParam.getOrg();
        lecTeacherListParam.setOrgStr(getCompletePath(path, org));
        log.error("setOrgStr耗时"+(date.getTime()-(new Date().getTime())));
        // 1. 查询当前教师下的课程
         date = new Date();
        List<LecTeacherVO> tealist = lecTeacherDao.list1(lecTeacherListParam);
        log.error("第一个sql耗时"+(date.getTime()-(new Date().getTime())));


        date = new Date();
        List<LecCourseEntity> courseList = lecCourseDao.listByTea(lecTeacherListParam);
        log.error("第二个sql耗时"+(date.getTime()-(new Date().getTime())));

        // 查询相关课程
        date = new Date();
        String tempFolder = lecCourseService.createTempFolder(courseList);
        log.error("查询课程耗时"+(date.getTime()-(new Date().getTime())));


        date = new Date();
        List<LecTeacherExportVO> lecTeacherExportVOS = getLecTeacherExportVOS(tealist);
        log.error("getLecTeacherExportVOS耗时"+(date.getTime()-(new Date().getTime())));
        if(CollectionUtil.isEmpty(lecTeacherExportVOS)){
            lecTeacherExportVOS.add(new LecTeacherExportVO());
        }
        date = new Date();
        ExcelWriter writer = ExcelUtil.getWriter(tempFolder + "讲师列表.xlsx", "教师信息");
        writer.setHeaderAlias(LecTeacherExportVO.headerAlias);
        CellStyle headCellStyleSheet2 = writer.getHeadCellStyle();
        ExcelsUtil.setCommonHeader(headCellStyleSheet2);
        writer.write(lecTeacherExportVOS, true);
        log.error("writer写入耗时" + (date.getTime()-(new Date().getTime())));
        writer.close();


        date = new Date();
        File zip = ZipUtil.zip(tempFolder);
        log.error("zip创建耗时" + (date.getTime()-(new Date().getTime())));
        log.error("=========生成临时文件目录==========" + tempFolder);
        date = new Date();
        log.info("该zip 文件：" + zip.getName());
        FileDownUtil.downTemporaryFile(tempFolder, zip, "讲师数据导出.zip");
        log.error("压缩zip耗时"+(date.getTime()-(new Date().getTime())));
        // 执行文件的删除
        Date end = new Date();
        log.error("总耗时" + (end.getTime()-start.getTime()));


    }

    /**
     * 获取转换之后的对象
     * @param list
     * @return
     */
    private List<LecTeacherExportVO> getLecTeacherExportVOS(List<LecTeacherVO> list) {


        List<LecTeacherVO> lecTeacherVOS = loadLecTeacherVOProp(list);
        List<LecTeacherExportVO> lecTeacherExportVOS = LecTeacherExportVO.convertToLecTeacherExportVOs(lecTeacherVOS);

        return lecTeacherExportVOS;
    }


    @Override
    @Transactional
    public void add(LecTeacherAddDTO addDTO) {
        String path;
        LecTeacherEntity entity = new LecTeacherEntity();
        BeanUtils.copyProperties(addDTO, entity);
        if(ObjectUtil.isNotNull(addDTO.getOrg())){
            OaLearnClassEntity learnClass = oaLearnClassDao.selectById(addDTO.getOrg());
            if (learnClass == null) {
                throw new ServiceException("上级单位不存在");
            }
            path = learnClass.getPath() + learnClass.getId() + ",";
            entity.setPath(path);
        }
        if(CollectionUtil.isNotEmpty(addDTO.getTypes())){
            entity.setTypes(JSONUtil.parseArray(addDTO.getTypes()).toString());
        }
        if(ObjectUtil.isNotNull(addDTO.getOrg())){
            entity.setOrg(String.valueOf(addDTO.getOrg()));
        }
        // 管理员账号
        OaAdminAddDTO dto = new OaAdminAddDTO();
        dto.setPid(addDTO.getOrg());
        dto.setName(addDTO.getName());
        dto.setPhone(addDTO.getAccount());
        dto.setPname(addDTO.getName());
        dto.setRoleId(AdminRoleEnum.TEACHER.getCode());
        dto.setPassword("000000");

        // 添加前查找数据库中是否存在该账户
        List<OaAdminEntity> oaAdminEntityList = oaAdminService.list(new LambdaQueryWrapper<OaAdminEntity>()
                .eq(OaAdminEntity::getAdTel, addDTO.getAccount()));
        if(oaAdminEntityList == null || oaAdminEntityList.size() == 0){
            oaAdminService.add(dto);
        }else{
            log.error(addDTO.getAccount()+"在oaAdmin中已存在");
            throw new ServiceException(addDTO.getAccount()+"在oaAdmin中已存在");
        }
        // 教师账号
        List<LecTeacherEntity> lecTeacherEntities = lecTeacherDao.selectList(new LambdaQueryWrapper<LecTeacherEntity>().eq(LecTeacherEntity::getAccount, addDTO.getAccount()));
        if(lecTeacherEntities == null || lecTeacherEntities.size() == 0){
            lecTeacherDao.insert(entity);
        }else {
            log.error(addDTO.getAccount()+"在lecTeacher中已存在");
            throw new ServiceException(addDTO.getAccount()+"在lecTeacher中已存在");
        }

    }

    @Override
    public LecTeacherInfoVO info(Integer id) {
        LecTeacherEntity entity = lecTeacherDao.selectById(id);

        if(entity == null){
            throw new ServiceException("未查询到当前记录！");
        }
        LecTeacherInfoVO vo = new LecTeacherInfoVO();
        BeanUtils.copyProperties(entity, vo);
        List<FileVO> fileVOs = lecResourceService.getFileVOs(entity.getHead(), ResourceEnum.IMAGE);
        if(CollectionUtil.isNotEmpty(fileVOs)){
            vo.setHead(fileVOs.get(0));
        }
        String[] split = StringUtils.split(entity.getPath(), ",");
        List<Integer> path = new ArrayList<>();
        if (ArrayUtils.isNotEmpty(split)) {
            for (String str : split) {
                if (!StringUtils.equals("0", str)) {
                    path.add(Integer.valueOf(str));
                }
            }
        }
        vo.setPath(path);
        vo.setTypes(JSONUtil.toList(entity.getTypes(), List.class));
        return vo;
    }

    @Autowired
    private OaAdminDao oaAdminDao;

    @Override
    @Transactional
    public void update(LecTeacherAddDTO addDTO) {
        LecTeacherEntity entity = lecTeacherDao.selectById(addDTO.getId());
        if (entity == null) {
            throw new ServiceException("讲师不存在");
        }
        if (!StringUtils.equals(entity.getAccount(), addDTO.getAccount())) {
            if (oaAdminDao.selectByPhone(addDTO.getAccount()) != null) {
                throw new ServiceException("账号已存在");
            }
        }
        oaAdminDao.update(new OaAdminEntity().setAdTel(addDTO.getAccount()).setPid(addDTO.getOrg()),
                new QueryWrapper<OaAdminEntity>().eq("ad_tel", entity.getAccount()));

        String path;
        OaLearnClassEntity learnClass = oaLearnClassDao.selectById(addDTO.getOrg());
        if (learnClass == null) {
            throw new ServiceException("上级单位不存在");
        }
        path = learnClass.getPath() + learnClass.getId() + ",";

        LecTeacherEntity update = new LecTeacherEntity();
        BeanUtils.copyProperties(addDTO, update);
        update.setPath(path);
        update.setTypes(JSONUtil.parseArray(addDTO.getTypes()).toString());
        update.setOrg(String.valueOf(addDTO.getOrg()));
        
        lecTeacherDao.updateById(update);
    }

    @Override
    @Transactional
    public void delete(List<Integer> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return;
        }
        List<LecTeacherEntity> list = lecTeacherDao.selectList(new QueryWrapper<LecTeacherEntity>().in("id", ids));
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        lecTeacherDao.delete(new QueryWrapper<LecTeacherEntity>().in("id", ids));
        lecCourseDao.delete(new QueryWrapper<LecCourseEntity>().in("teacher_id", ids));
        List<String> tels = list.stream().map(LecTeacherEntity::getAccount).collect(Collectors.toList());
        oaAdminDao.delete(new QueryWrapper<OaAdminEntity>().in("ad_tel", tels));
    }

    @Override
    public void reset(Integer id) {
        LecTeacherEntity info = lecTeacherDao.selectById(id);
        if (info == null) {
            throw new ServiceException("讲师不存在");
        }

        String  adminMark = "0";
        OaAdminEntity admin = userInfoHolder.getAdmin();
        // teachers are only allowed to check their own information
        if(admin.getRoleId().equals(AdminRoleEnum.TEACHER.getCode())){
            if(info.getAccount().equals(admin.getAdTel()) == false){
                throw new ServiceException("当前用户没有权限修改此用户信息！");
            }
        }
        // whether other role can match the current user
        if( info.getPath().contains( String.valueOf(admin.getPid()) ) == false
                && adminMark.equals(String.valueOf(admin.getPid())) == false ){
            throw new ServiceException("当前用户没有权限修改此用户信息！");
        }
        oaAdminDao.update(new OaAdminEntity().setAdPwd(passwordEncoder.encode("000000")),
                new QueryWrapper<OaAdminEntity>().eq("ad_tel", info.getAccount()));
    }

    /**
     * 模板下载
     */
    @Override
    public void templateDownload() throws IOException {

        // 创建新的Excel工作簿
        Workbook workbook = new XSSFWorkbook();
        // 创建新的工作表
        Sheet sheet = workbook.createSheet("Sheet1");
        // 创建表头行
        Row headerRow = sheet.createRow(0);
        // 在第一列设置表头文本
        headerRow.createCell(0).setCellValue("姓名");
        // 在第二列设置表头文本
        headerRow.createCell(1).setCellValue("性别");
        // 在第三列设置表头文本
        headerRow.createCell(2).setCellValue("出生年月");
        // 在第四列设置表头文本
        headerRow.createCell(3).setCellValue("年龄");
        // 在第五列设置表头文本
        headerRow.createCell(4).setCellValue("单位职务");
        // 在第六列设置表头文本
        headerRow.createCell(5).setCellValue("联系方式");

        // 将单位职务设置列宽为69
        sheet.setColumnWidth(4, 69 * 256);
        // 将联系方式设置列宽为49
        sheet.setColumnWidth(5, 49 * 256);
        // 设置响应内容类型为Excel文件类型
        httpServletResponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        // 设置响应头，将文件作为附件下载，文件名为ExcelDownload.xlsx
        httpServletResponse.setHeader("Content-Disposition", "attachment; filename=讲师团名单导入模板.xlsx");
        // 获取输出流，将工作簿写入输出流中
        OutputStream outputStream = httpServletResponse.getOutputStream();
        // 将工作簿写入输出流中
        workbook.write(outputStream);
        // 关闭工作簿，释放资源
        workbook.close();

    }

    @Override
    @Transactional
    public List<String> batchImport(MultipartFile file) {

        List<String> errorLogs = Lists.newArrayList();

        try {
            ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
            reader.setHeaderAlias(LecTeacherExcelVO.importAlias);
            List<LecTeacherExcelVO> data = reader.readAll(LecTeacherExcelVO.class);

            for (LecTeacherExcelVO datum : data) {

            }
            for (int i = 0; i < data.size(); i++) {

                LecTeacherExcelVO lecTeacherExcelVO = data.get(i);
                if(StrUtil.isBlank(lecTeacherExcelVO.getName())){
                    String errorLog = "第" + (i+2) + "行:"+"用户名不能为空!";
                    errorLogs.add(errorLog);
                    continue;
                }
                if(StrUtil.isBlank(lecTeacherExcelVO.getAccount())){
                    String errorLog = "第" + (i+2) + "行:"+"账号不能为空!";
                    errorLogs.add(errorLog);
                    continue;
                }
                if(StrUtil.isBlank(lecTeacherExcelVO.getBirthday())){
                    String errorLog = "第" + (i+2) + "行:"+"出生年月为空 无法计算年龄!";
                    errorLogs.add(errorLog);
                }
                try {
                    // 获取当前用户的机构
                    LecTeacherAddDTO addDTO = new LecTeacherAddDTO();
                    // 账号
                    addDTO.setAccount(lecTeacherExcelVO.getAccount());
                    addDTO.setPhone(lecTeacherExcelVO.getAccount());
                    List<List<String>> types = new ArrayList<>();
                    ArrayList<String> childList = new ArrayList<>();
                    childList.add("1");
                    types.add(childList);
                    addDTO.setTypes(types);
                    //姓名
                    addDTO.setName(lecTeacherExcelVO.getName());
                    // 机构
                    addDTO.setOrg(1);
                    // 性别
                    if(lecTeacherExcelVO.getSex()!=null && "男".equals(lecTeacherExcelVO.getSex())){
                        addDTO.setSex(1);
                    }
                    if(lecTeacherExcelVO.getSex()!=null && "女".equals(lecTeacherExcelVO.getSex())){
                        addDTO.setSex(2);
                    }
                    // 年龄
                    if(StringUtils.isEmpty(lecTeacherExcelVO.getAge())){
                        Integer age = calculateAge(lecTeacherExcelVO);
                        addDTO.setAge(age);
                    }else {
                        addDTO.setAge(Integer.parseInt(lecTeacherExcelVO.getAge()));
                    }
                    // 职位
                    if(!StringUtils.isEmpty(lecTeacherExcelVO.getProfession())){
                        addDTO.setProfession(lecTeacherExcelVO.getProfession());
                    }
                    add(addDTO);
                } catch (Exception e) {
                    log.error(e.getMessage());
                    String errorLog = "第" + (i+2) + "行: 用户名： " +lecTeacherExcelVO.getName() + "账号：" + lecTeacherExcelVO.getAccount() +"导入失败：" + e.getMessage();
                    errorLogs.add(errorLog);
                    continue;
                }
            }
        } catch (IOException e) {
            throw new ServiceException(" 解析excel文件异常 ");
        }

        return errorLogs;
    }
    public static Integer calculateAge(LecTeacherExcelVO lecTeacherExcelVO) throws Exception {
        String birthDate = lecTeacherExcelVO.getBirthday();
        String name = lecTeacherExcelVO.getName();

        // 定义日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM");
        Date birthDateAsDate;
        // 尝试解析日期
        try {
            birthDateAsDate = sdf.parse(birthDate);
        } catch (ParseException e) {
            log.error(name+"出生年月格式不对 正确格式为 年.月");
            return null;
        }
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        LocalDate birthLocalDate = birthDateAsDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        // 计算时间段
        Period period = Period.between(birthLocalDate, currentDate);
        // 返回年龄
        return period.getYears();
    }

    @Override
    public LecCurrentTeaVO getUserLinkedTeaInfo() {

        Integer roleId = userInfoHolder.getAdmin().getRoleId();
        String account = userInfoHolder.getAdmin().getAdTel();
        Integer teaId = null;
        if(roleId == 2){
            LecTeacherEntity lecTeacherEntity = lecTeacherDao.selectByAccount(account);
            teaId = lecTeacherEntity.getId();
        }
        LecCurrentTeaVO lecCurrentTeaVO = new LecCurrentTeaVO();
        lecCurrentTeaVO.setRoleId(roleId);
        lecCurrentTeaVO.setTeaId(teaId);

        return  lecCurrentTeaVO;
    }

    @Override
    public void register(HttpServletRequest request, String codeInRequest) {

        // 验证用户验证码
        HttpSession session = request.getSession();
        validateCode(session, codeInRequest);
    }

    @Override
    public int countByPath(String path) {
        return lecTeacherDao.countByPath(path);
    }

    @Override
    public LecTeacherEntity getByAccount(String adTel) {
        QueryWrapper<LecTeacherEntity> qw = new QueryWrapper<>();
        qw.lambda().eq( LecTeacherEntity::getAccount, adTel );
        return getOne(qw);
    }

    @Override
    public List<TeacherLectureCountVo> queryTeacherLectureCount(Date startTime, Date endTime, Integer type) {
        List<TeacherLectureCountVo> lectureCountVos = lecTeacherDao.queryTeacherLectureCount(startTime, endTime, type);
        return lectureCountVos;
    }

    @Override
    public List<LecTeacherCourseDetailVo> queryCourseTypeSeries(Date startTime, Date endTime, Long teacherId, Integer type) {
        List<LecTeacherCourseDetailVo> list =lecTeacherDao.queryCourseTypeSeries(startTime, endTime, teacherId, type);
        return list;
    }


    private void validateCode( HttpSession session,String codeInRequest)
    {
        ImageCodeDTO codeInSession = (ImageCodeDTO) session.getAttribute(ValidateController.SESSION_KEY_IMAGE_CODE);

        if (StringUtils.isBlank(codeInRequest)) {
            throw new ServiceException("验证码不能为空！");
        }
        if (codeInSession == null) {
            throw new ServiceException("验证码不存在！");
        }
        if (codeInSession.isExpire()) {
            session.removeAttribute( ValidateController.SESSION_KEY_IMAGE_CODE );
            throw new ServiceException("验证码已过期！");
        }
        if (!StringUtils.equalsIgnoreCase(codeInSession.getCode(), codeInRequest)) {
            throw new ServiceException("验证码不正确！");
        }
        session.removeAttribute( ValidateController.SESSION_KEY_IMAGE_CODE );
    }

}